/*************************************************
 * HISTORY:                                      *
 *	06/22/2020 pyx : Created.                    *
 *	06/01/2022 pyx : Edited.                     *
=================================================*/

#include "DADumperConnector.h"

Connector::Connector(std::string directory, std::string vectorsfile)
{
    this->vectorsfile = vectorsfile;

    this->directory = directory;
    if (directory[directory.size() - 1] != '/')
        directory.push_back('/');

    startDump();
}

Connector::Connector(std::string directory)
{
    this->vectorsfile.clear();
    this->directory = directory;
    if (directory[directory.size() - 1] != '/')
        directory.push_back('/');

    startDump();
}

void Connector::startDump()
{

    // edge.json: fid->(ref)->fid
    std::string jsonfilepath = "edge.json";
    std::ofstream jsonfile;
    jsonfile.open(jsonfilepath, std::ios::out | std::ios::trunc);
    if (!jsonfile.good())
    {
        std::cout << "json file write fail" << jsonfilepath << "\n";
        exit(1);
    }
    jsonfile << "[" << std::endl;
    jsonfile.flush();

    jsonfile.close();

    ////////////////////////////////////////////////
    // all symbol def-use relationship in file level
    std::string symmdgfilepath = "symbol.mdg";
    std::ofstream symmdgfile;
    symmdgfile.open(symmdgfilepath, std::ios::out | std::ios::trunc);
    if (!symmdgfile.good())
    {
        std::cout << "mdg file write fail" << symmdgfilepath << "\n";
        exit(1);
    }

    symmdgfile.close();

    /////////////////////////////////////////////////
    // filed type def-use relationship in file level
    std::string fieldmdgfilepath = "field.mdg";
    std::ofstream fieldmdgfile;
    fieldmdgfile.open(fieldmdgfilepath, std::ios::out | std::ios::trunc);
    if (!fieldmdgfile.good())
    {
        std::cout << "mdg file write fail" << fieldmdgfilepath << "\n";
        exit(1);
    }
    fieldmdgfile.close();

    /////////////////////////////////////////////////
    // f-gv type def-use relationship in file level
    std::string functgvmdgfilepath = "f-gv.mdg";
    std::ofstream functgvmdgfile;
    functgvmdgfile.open(functgvmdgfilepath, std::ios::out | std::ios::trunc);
    if (!functgvmdgfile.good())
    {
        std::cout << "mdg file write fail" << functgvmdgfilepath << "\n";
        exit(1);
    }
    functgvmdgfile.close();

    /////////////////////////////////////////////////
    // function type def-use relationship in file level
    std::string functmdgfilepath = "function.mdg";
    std::ofstream functmdgfile;
    functmdgfile.open(functmdgfilepath, std::ios::out | std::ios::trunc);
    if (!functmdgfile.good())
    {
        std::cout << "mdg file write fail" << functmdgfilepath << "\n";
        exit(1);
    }
    functmdgfile.close();

    /////////////////////////////////////////////////
    // gv type def-use relationship in file level
    std::string gvmdgfilepath = "gv.mdg";
    std::ofstream gvmdgfile;
    gvmdgfile.open(gvmdgfilepath, std::ios::out | std::ios::trunc);
    if (!gvmdgfile.good())
    {
        std::cout << "mdg file write fail" << gvmdgfilepath << "\n";
        exit(1);
    }
    gvmdgfile.close();

    /////////////////////////////////////////////////
    // macro type def-use relationship in file level
    std::string macromdgfilepath = "macro.mdg";
    std::ofstream macromdgfile;
    macromdgfile.open(macromdgfilepath, std::ios::out | std::ios::trunc);
    if (!macromdgfile.good())
    {
        std::cout << "mdg file write fail" << macromdgfilepath << "\n";
        exit(1);
    }
    macromdgfile.close();

    /////////////////////////////////////////////////
    // type type def-use relationship in file level
    std::string typemdgfilepath = "type.mdg";
    std::ofstream typemdgfile;
    typemdgfile.open(typemdgfilepath, std::ios::out | std::ios::trunc);
    if (!typemdgfile.good())
    {
        std::cout << "mdg file write fail" << typemdgfilepath << "\n";
        exit(1);
    }
    typemdgfile.close();

    /////////////////////////////////////////////////
    // enum type def-use relationship in file level
    std::string enummdgfilepath = "enum.mdg";
    std::ofstream enummdgfile;
    enummdgfile.open(enummdgfilepath, std::ios::out | std::ios::trunc);
    if (!enummdgfile.good())
    {
        std::cout << "mdg file write fail" << enummdgfilepath << "\n";
        exit(1);
    }
    enummdgfile.close();

    /////////////////////////////////////////////////
    // struct type def-use relationship in file level
    std::string structmdgfilepath = "struct.mdg";
    std::ofstream structmdgfile;
    structmdgfile.open(structmdgfilepath, std::ios::out | std::ios::trunc);
    if (!structmdgfile.good())
    {
        std::cout << "mdg file write fail" << structmdgfilepath << "\n";
        exit(1);
    }
    structmdgfile.close();

    /////////////////////////////////////////////////
    // union type def-use relationship in file level
    std::string unionmdgfilepath = "union.mdg";
    std::ofstream unionmdgfile;
    unionmdgfile.open(unionmdgfilepath, std::ios::out | std::ios::trunc);
    if (!unionmdgfile.good())
    {
        std::cout << "mdg file write fail" << unionmdgfilepath << "\n";
        exit(1);
    }
    unionmdgfile.close();

    /////////////////////////////////////////////////
    // typedef type def-use relationship in file level
    std::string typedefmdgfilepath = "typedef.mdg";
    std::ofstream typedefmdgfile;
    typedefmdgfile.open(typedefmdgfilepath, std::ios::out | std::ios::trunc);
    if (!typedefmdgfile.good())
    {
        std::cout << "mdg file write fail" << typedefmdgfilepath << "\n";
        exit(1);
    }
    typedefmdgfile.close();

    ////////////////////////////////////////////////
    // inc relationship, direct,not transitive
    std::string incmdgfilepath = "include.mdg";
    std::ofstream incmdgfile;
    incmdgfile.open(incmdgfilepath, std::ios::out | std::ios::trunc);
    if (!incmdgfile.good())
    {
        std::cout << "mdg file write fail" << incmdgfilepath << "\n";
        exit(1);
    }

    incmdgfile.close();

    ////////////////////////////////////////////////
    std::string inctsejsonfilepath = "includeedge_internal.json";
    std::ofstream inctsejsonfile;
    inctsejsonfile.open(inctsejsonfilepath, std::ios::out | std::ios::trunc);
    if (!inctsejsonfile.good())
    {
        std::cout << "inctsejsonfile write fail" << inctsejsonfilepath << "\n";
        exit(1);
    }
    inctsejsonfile << "[" << std::endl;
    inctsejsonfile.flush();

    inctsejsonfile.close();

    ////////////////////////////////////////////////
    std::string symtsejsonfilepath = "edge_internal.json";
    std::ofstream symtsejsonfile;
    symtsejsonfile.open(symtsejsonfilepath, std::ios::out | std::ios::trunc);
    if (!symtsejsonfile.good())
    {
        std::cout << "symtsejsonfile write fail" << symtsejsonfilepath << "\n";
        exit(1);
    }
    symtsejsonfile << "[" << std::endl;
    symtsejsonfile.flush();

    symtsejsonfile.close();

    /////////////////////////////////////////////////
    std::string fgvtsejsonfilepath = "fgvedge_internal.json";
    std::ofstream fgvtsejsonfile;
    fgvtsejsonfile.open(fgvtsejsonfilepath, std::ios::out | std::ios::trunc);
    if (!fgvtsejsonfile.good())
    {
        std::cout << "fgvtsejsonfile write fail" << fgvtsejsonfilepath << "\n";
        exit(1);
    }
    fgvtsejsonfile << "[" << std::endl;

    fgvtsejsonfile.flush();
    fgvtsejsonfile.close();

    /////////////////////////////////////////////////
    std::string funtsejsonfilepath = "functionedge_internal.json";
    std::ofstream funtsejsonfile;
    funtsejsonfile.open(funtsejsonfilepath, std::ios::out | std::ios::trunc);
    if (!funtsejsonfile.good())
    {
        std::cout << "funtsejsonfile write fail" << funtsejsonfilepath << "\n";
        exit(1);
    }
    funtsejsonfile << "[" << std::endl;

    funtsejsonfile.flush();
    funtsejsonfile.close();

    ////////////////////////////////////////////////
    std::string filenodepath = "filenode.json";
    std::ofstream filenode;
    filenode.open(filenodepath, std::ios::out | std::ios::trunc);
    if (!filenode.good())
    {
        std::cout << "node json file write fail" << filenodepath << "\n";
        exit(1);
    }
    filenode << "[" << std::endl;
    ////////////////////////////////////////////////
    std::string includefilepath = "includeedge.json";
    std::ofstream includefile;
    includefile.open(includefilepath, std::ios::out | std::ios::trunc);
    if (!includefile.good())
    {
        std::cout << "include json file write fail" << includefilepath << "\n";
        exit(1);
    }
    includefile << "[" << std::endl;
    includefile.flush();

    includefile.close();
    ////////////////////////////////////////////////
    try
    {
        driver = get_driver_instance();
        con = driver->connect(DBHOST, USER, PASSWORD);
        con->setAutoCommit(0);
        std::cout << "Connected!DataBase connection autocommit mode = " << con->getAutoCommit() << std::endl;

        con->setSchema("dadb");

        stmt = con->createStatement();
        sql::ResultSet *res = stmt->executeQuery("SELECT * FROM filetable;"); // debug

        int num = res->rowsCount();

        if (num == 0)
        {
            std::cout << "no file in filetable!" << std::endl;

            exit(1);
        }

        bool begin = true;

        while (res->next())
        {

            if (begin)
                begin = false;
            else
                filenode << "," << std::endl;

            unsigned fid = res->getInt("fid");
            std::string path = res->getString("filepath");
            currfilepath = path;
            currfid = fid;

            // depfilelist.clear();
            // filesymbolmap.clear();

            std::unordered_set<unsigned>().swap(depfilelist);
            std::unordered_set<unsigned>().swap(depfilelist_funct);
            std::unordered_set<unsigned>().swap(depfilelist_gv);
            std::unordered_set<unsigned>().swap(depfilelist_macro);
            std::unordered_set<unsigned>().swap(depfilelist_type);
            std::unordered_set<unsigned>().swap(depfilelist_enum);
            std::unordered_set<unsigned>().swap(depfilelist_struct);
            std::unordered_set<unsigned>().swap(depfilelist_union);
            std::unordered_set<unsigned>().swap(depfilelist_typedef);
            std::unordered_set<unsigned>().swap(depfilelist_field);
            std::unordered_map<unsigned, std::unordered_set<unsigned>>().swap(filesymbolmap);

            filenode << "{" << std::endl;
            filenode << "\"fid\" : " << fid << "," << std::endl;
            filenode << "\"path\" : \"" << path << "\"" << std::endl;
            filenode << "}" << std::endl;

            findFileDep(); // ENTRY!!!
        }

        std::cout << "all file in filetable dumped!" << std::endl;

        filenode << "]" << std::endl;

        filenode.flush();

        filenode.close();
        ////////////////////////////////////////////////
        jsonfile.open(jsonfilepath, std::ios::out | std::ios::app);
        if (!jsonfile.good())
        {
            std::cout << "json file write fail" << jsonfilepath << "\n";
            exit(1);
        }

        jsonfile << "]" << std::endl;
        jsonfile.flush();
        jsonfile.close();
        ////////////////////////////////////////////////

        includefile.open(includefilepath, std::ios::out | std::ios::app);
        if (!includefile.good())
        {
            std::cout << "include json file write fail" << includefilepath << "\n";
            exit(1);
        }
        includefile << "]" << std::endl;
        includefile.flush();

        includefile.close();

        ////////////////////////////////////////////////

        inctsejsonfile.open(inctsejsonfilepath, std::ios::out | std::ios::app);
        if (!inctsejsonfile.good())
        {
            std::cout << "inctsejsonfile  write fail" << inctsejsonfilepath << "\n";
            exit(1);
        }
        inctsejsonfile << "]" << std::endl;
        inctsejsonfile.flush();

        inctsejsonfile.close();

        ////////////////////////////////////////////////

        symtsejsonfile.open(symtsejsonfilepath, std::ios::out | std::ios::app);
        if (!symtsejsonfile.good())
        {
            std::cout << "symtsejsonfile  write fail" << symtsejsonfilepath << "\n";
            exit(1);
        }
        symtsejsonfile << "]" << std::endl;
        symtsejsonfile.flush();

        symtsejsonfile.close();
        ////////////////////////////////////////////////

        fgvtsejsonfile.open(fgvtsejsonfilepath, std::ios::out | std::ios::app);
        if (!fgvtsejsonfile.good())
        {
            std::cout << "fgvtsejsonfile write fail" << fgvtsejsonfilepath << "\n";
            exit(1);
        }
        fgvtsejsonfile << "]" << std::endl;

        fgvtsejsonfile.flush();
        fgvtsejsonfile.close();

        ////////////////////////////////////////////////

        funtsejsonfile.open(funtsejsonfilepath, std::ios::out | std::ios::app);
        if (!funtsejsonfile.good())
        {
            std::cout << "funtsejsonfile write fail" << funtsejsonfilepath << "\n";
            exit(1);
        }
        funtsejsonfile << "]" << std::endl;

        funtsejsonfile.flush();
        funtsejsonfile.close();

        ////////////////////////////////////////////////

        delete res;
        std::cout << "ok connector part 1!" << std::endl;
    }
    catch (sql::SQLException &e)
    {
        std::cout << "ERROR: " << e.what();
        std::cout << " (MySQL error code: " << e.getErrorCode();
        std::cout << ", SQLState: " << e.getSQLState() << ")" << std::endl;

        exit(1);
    }
    catch (std::runtime_error &e)
    {
        std::cout << "ERROR: " << e.what() << std::endl;

        exit(1);
    }

    dumpSymbolNode(); // ENTRY 2!!!
    std::cout << "ok part2" << std::endl;

    std::string symbolnodepath = "refnode.json";
    std::ofstream symbolnode;
    symbolnode.open(symbolnodepath, std::ios::out | std::ios::trunc);
    if (!symbolnode.good())
    {
        std::cout << "refnode json file write fail" << symbolnodepath << "\n";
        exit(1);
    }
    symbolnode << "[" << std::endl;
    symbolnode.close();

    dumpRefNode("globaldeftable"); // ENTRY 3!!!
    std::cout << "ok part3" << std::endl;

    symbolnode.open(symbolnodepath, std::ios::out | std::ios::app);
    if (!symbolnode.good())
    {
        std::cout << "refnode json file write fail" << symbolnodepath << "\n";
        exit(1);
    }
    symbolnode << "," << std::endl;
    symbolnode.close();

    dumpRefNode("globaldectable"); // ENTRY 4!!!
    std::cout << "ok part4" << std::endl;

    symbolnode.open(symbolnodepath, std::ios::out | std::ios::app);
    if (!symbolnode.good())
    {
        std::cout << "refnode json file write fail" << symbolnodepath << "\n";
        exit(1);
    }
    symbolnode << "," << std::endl;
    symbolnode.close();

    dumpRefNode("reftable"); // ENTRY 5!!!
    std::cout << "ok part5" << std::endl;

    symbolnode.open(symbolnodepath, std::ios::out | std::ios::app);
    if (!symbolnode.good())
    {
        std::cout << "refnode json file write fail" << symbolnodepath << "\n";
        exit(1);
    }
    symbolnode << "]" << std::endl;
    symbolnode.close();

    dumpSymbolDep(); // ENTRY 6!!!
    std::cout << "ok part6" << std::endl;

    dumpFileDefSymMap(); // ENTRY 7!!!
    std::cout << "ok part7" << std::endl;

    dumpNewVectors(); // ENTRY 8!!!
    std::cout << "ok part8" << std::endl;

    dumpOnehotVectors(); // ENTRY 9!!!
    std::cout << "ok part9" << std::endl;
}

Connector::~Connector()
{
    /*
    for (auto iter : filesymbolmap)
    {
        for (auto iter2 : iter.second)
            delete iter2;
    }
*/
    try
    {
        con->commit();

        std::cout << "Cleaning up the resources .." << std::endl;

        /* Clean up */
        // delete res;
        // delete stmt;
        // delete prep_stmt;
        con->close();
        // delete con;
        std::cout << "out ~connector()" << std::endl;
    }
    catch (sql::SQLException &e)
    {
        std::cout << "ERROR: " << e.what();
        std::cout << " (MySQL error code: " << e.getErrorCode();
        std::cout << ", SQLState: " << e.getSQLState() << ")" << std::endl;

        exit(1);
    }
    catch (std::runtime_error &e)
    {
        std::cout << "ERROR: " << e.what() << std::endl;

        exit(1);
    }
}

void Connector::commit()
{
    try
    {
        std::cout << "\tCommitting outstanding updates to the database .." << std::endl;
        con->commit();
    }
    catch (sql::SQLException &e)
    {
        std::cout << "ERROR: " << e.what();
        std::cout << " (MySQL error code: " << e.getErrorCode();
        std::cout << ", SQLState: " << e.getSQLState() << ")" << std::endl;

        if (e.getErrorCode() == 1047)
        {
            /*
            Error: 1047 SQLSTATE: 08S01 (ER_UNKNOWN_COM_ERROR)
            Message: Unknown command
            */
            std::cout << "/nYour server does not seem to support Prepared Statements at all. ";
            std::cout << "Perhaps MYSQL < 4.1?" << std::endl;
        }

        exit(1);
    }
    catch (std::runtime_error &e)
    {
        std::cout << "ERROR: " << e.what() << std::endl;

        exit(1);
    }
}
/*
sql::ResultSet* Connector::searchSymbol(std::string name){


    std::string query = "SELECT * FROM symboltable where name = \"" + name + "\";";
    stmt = con -> createStatement();

    return stmt->executeQuery(query);
}
*/
unsigned Connector::getfid(std::string filepath)
{

    std::string query = "SELECT fid FROM filetable where BINARY filepath = \"" + filepath + "\";";
    stmt = con->createStatement();

    sql::ResultSet *rs = stmt->executeQuery(query);

    int num = rs->rowsCount();

    if (num == 0)
    {
        std::cout << "file not found!@" << filepath << std::endl;
        delete rs;
        return 0;
    }

    assert(num == 1);

    unsigned fid;

    if (rs->next())
    {
        fid = rs->getInt("fid");
    }

    assert(fid > 0);
    delete rs;
    return fid;
}

std::string Connector::getfilepath(unsigned fid)
{

    assert(fid > 0);

    std::string query = "SELECT filepath FROM filetable where fid = " + std::to_string(fid) + ";";
    stmt = con->createStatement();

    sql::ResultSet *rs = stmt->executeQuery(query);

    int num = rs->rowsCount();

    if (num == 0)
    {
        std::cout << "fid not found!@" << fid << std::endl;
        delete rs;

        return 0;
    }

    assert(num == 1);

    std::string filepath;

    if (rs->next())
    {
        filepath = rs->getString("filepath");
    }

    assert(!filepath.empty());

    delete rs;
    return filepath;
}

std::string Connector::getSymbolName(unsigned sid)
{

    assert(sid > 0);

    std::string query = "SELECT name FROM symboltable where sid = " + std::to_string(sid) + ";";
    stmt = con->createStatement();

    sql::ResultSet *rs = stmt->executeQuery(query);

    int num = rs->rowsCount();

    if (num == 0)
    {
        delete rs;
        return nullptr;
    }

    assert(num == 1);

    if (rs->next())
    {

        std::string name = rs->getString("name");

        delete rs;
        return name;
    }
    else
    {
        std::cout << "internal error in getSymbolName"
                  << "\n";

        exit(1);
    }
}

SymbolType Connector::getSymbolType(unsigned sid)
{

    assert(sid > 0);

    std::string query = "SELECT symboltype FROM symboltable where sid = " + std::to_string(sid) + ";";
    stmt = con->createStatement();

    sql::ResultSet *rs = stmt->executeQuery(query);

    int num = rs->rowsCount();

    if (num == 0)
    {
        delete rs;
        return ST_Max;
    }

    assert(num == 1);

    if (rs->next())
    {

        int st = rs->getInt("symboltype");

        delete rs;
        return (SymbolType)st;
    }
    else
    {
        std::cout << "internal error in getSymbolName"
                  << "\n";

        exit(1);
    }
}

std::string Connector::getSymbolQN(unsigned sid)
{

    assert(sid > 0);

    std::string query = "SELECT signature FROM symboltable where sid = " + std::to_string(sid) + ";";
    stmt = con->createStatement();

    sql::ResultSet *rs = stmt->executeQuery(query);

    int num = rs->rowsCount();

    if (num == 0)
    {
        delete rs;
        return nullptr;
    }

    assert(num == 1);

    if (rs->next())
    {
        std::string sig = rs->getString("signature");
        delete rs;
        return sig;
    }
    else
    {
        std::cout << "internal error in getSymbolQN"
                  << "\n";

        exit(1);
    }
}

void Connector::dumpSymbolNode()
{

    std::string symbolnodepath = "symbolnode.json";
    std::ofstream symbolnode;
    symbolnode.open(symbolnodepath, std::ios::out | std::ios::trunc);
    if (!symbolnode.good())
    {
        std::cout << "node json file write fail" << symbolnodepath << "\n";
        exit(1);
    }
    symbolnode << "[" << std::endl;

    int startidx = 0;
    bool begin = true;

    try
    {
        while (true)
        {
            std::string query = "SELECT * FROM symboltable limit " + std::to_string(startidx) + "," + std::to_string(MAX_BATCH_SIZE) + ";";
            stmt = con->createStatement();

            sql::ResultSet *rs = stmt->executeQuery(query);

            int num = rs->rowsCount();

            std::cout << num << std::endl;

            if (num == 0 && begin)
            {
                std::cout << "no symbol in symboltable!" << std::endl;

                exit(1);
            }
            else if (num == 0)
            {
                break;
            }

            while (rs->next())
            {

                if (begin)
                    begin = false;
                else
                    symbolnode << "," << std::endl;

                unsigned sid = rs->getInt("sid");
                std::string qualifiedname = rs->getString("signature");
                int st = rs->getInt("symboltype");
                std::string name = rs->getString("name");
                assert(sid > 0);
                assert(st >= 0);

                symbolnode << "{" << std::endl;
                symbolnode << "\"sid\" : " << sid << "," << std::endl;
                symbolnode << "\"qualifiedname\" : \"" << qualifiedname << "\"," << std::endl;
                symbolnode << "\"symboltype\" : \"" << symbolTypeNames[st] << "\"," << std::endl;
                symbolnode << "\"name\" : \"" << name << "\"" << std::endl;
                symbolnode << "}" << std::endl;
            }

            delete rs;

            if (num < MAX_BATCH_SIZE)
            {
                symbolnode << "]" << std::endl;
                symbolnode.flush();

                symbolnode.close();
                break;
            }
            else
            {
                startidx += MAX_BATCH_SIZE;
            }
        }
    }
    catch (sql::SQLException &e)
    {
        std::cout << "ERROR: " << e.what();
        std::cout << " (MySQL error code: " << e.getErrorCode();
        std::cout << ", SQLState: " << e.getSQLState() << ")" << std::endl;

        if (e.getErrorCode() == 1047)
        {
            /*
            Error: 1047 SQLSTATE: 08S01 (ER_UNKNOWN_COM_ERROR)
            Message: Unknown command
            */
            std::cout << "/nYour server does not seem to support Prepared Statements at all. ";
            std::cout << "Perhaps MYSQL < 4.1?" << std::endl;
        }

        exit(1);
    }
    catch (std::runtime_error &e)
    {
        std::cout << "ERROR: " << e.what() << std::endl;

        exit(1);
    }
}

std::unordered_set<std::string> Connector::getSymbolDefFilepath(unsigned sid)
{
    try
    {
        std::string query = "SELECT filepath FROM globaldeftable,filetable WHERE globaldeftable.fid = filetable.fid AND sid=" + std::to_string(sid) + ";";
        stmt = con->createStatement();

        sql::ResultSet *rs = stmt->executeQuery(query);

        int num = rs->rowsCount();
        // std::cout<<num<<std::endl;

        std::unordered_set<std::string> ret;

        while (rs->next())
        {
            std::string filepath = rs->getString("filepath");

            assert(!filepath.empty());

            if (filepath.find(directory) == 0)
                ret.insert(filepath.substr(directory.length() + 1));
        }

        delete rs;
        return ret;
    }
    catch (sql::SQLException &e)
    {
        std::cout << "ERROR: " << e.what();
        std::cout << " (MySQL error code: " << e.getErrorCode();
        std::cout << ", SQLState: " << e.getSQLState() << ")" << std::endl;

        if (e.getErrorCode() == 1047)
        {
            /*
            Error: 1047 SQLSTATE: 08S01 (ER_UNKNOWN_COM_ERROR)
            Message: Unknown command
            */
            std::cout << "/nYour server does not seem to support Prepared Statements at all. ";
            std::cout << "Perhaps MYSQL < 4.1?" << std::endl;
        }

        exit(1);
    }
    catch (std::runtime_error &e)
    {
        std::cout << "ERROR: " << e.what() << std::endl;

        exit(1);
    }
}

std::unordered_set<std::string> Connector::getSymbolDefAndDecFilepath(unsigned sid)
{
    std::unordered_set<std::string> ret = getSymbolDefFilepath(sid);
    try
    {
        std::string query = "SELECT filepath FROM globaldectable,filetable WHERE globaldectable.fid = filetable.fid AND sid=" + std::to_string(sid) + ";";
        stmt = con->createStatement();

        sql::ResultSet *rs = stmt->executeQuery(query);

        int num = rs->rowsCount();
        // std::cout<<num<<std::endl;

        while (rs->next())
        {
            std::string filepath = rs->getString("filepath");

            assert(!filepath.empty());

            if (filepath.find(directory) == 0)
                ret.insert(filepath.substr(directory.length() + 1));
        }

        delete rs;
        return ret;
    }
    catch (sql::SQLException &e)
    {
        std::cout << "ERROR: " << e.what();
        std::cout << " (MySQL error code: " << e.getErrorCode();
        std::cout << ", SQLState: " << e.getSQLState() << ")" << std::endl;

        if (e.getErrorCode() == 1047)
        {
            /*
            Error: 1047 SQLSTATE: 08S01 (ER_UNKNOWN_COM_ERROR)
            Message: Unknown command
            */
            std::cout << "/nYour server does not seem to support Prepared Statements at all. ";
            std::cout << "Perhaps MYSQL < 4.1?" << std::endl;
        }

        exit(1);
    }
    catch (std::runtime_error &e)
    {
        std::cout << "ERROR: " << e.what() << std::endl;

        exit(1);
    }
}

void Connector::dumpSymbolDep()
{

    std::string symboldeppath = "symboldep.mdg";
    std::ofstream symboldep;
    symboldep.open(symboldeppath, std::ios::out | std::ios::trunc);
    if (!symboldep.good())
    {
        std::cout << "node mdg file write fail" << symboldeppath << "\n";
        exit(1);
    }

    std::string symboldepfilelevelallpath = "symboldep_filelevel_all.mdg";
    std::ofstream symboldepfilelevelall;
    symboldepfilelevelall.open(symboldepfilelevelallpath, std::ios::out | std::ios::trunc);
    if (!symboldepfilelevelall.good())
    {
        std::cout << "node mdg file write fail" << symboldepfilelevelallpath << "\n";
        exit(1);
    }

    std::string symboldepfilelevel0path = "symboldep_filelevel_0.mdg";
    std::ofstream symboldepfilelevel0;
    symboldepfilelevel0.open(symboldepfilelevel0path, std::ios::out | std::ios::trunc);
    if (!symboldepfilelevel0.good())
    {
        std::cout << "node mdg file write fail" << symboldepfilelevel0path << "\n";
        exit(1);
    }

    std::string symboldepfilelevel1path = "symboldep_filelevel_1.mdg";
    std::ofstream symboldepfilelevel1;
    symboldepfilelevel1.open(symboldepfilelevel1path, std::ios::out | std::ios::trunc);
    if (!symboldepfilelevel1.good())
    {
        std::cout << "node mdg file write fail" << symboldepfilelevel1path << "\n";
        exit(1);
    }

    std::string symboldepfilelevel2path = "symboldep_filelevel_2.mdg";
    std::ofstream symboldepfilelevel2;
    symboldepfilelevel2.open(symboldepfilelevel2path, std::ios::out | std::ios::trunc);
    if (!symboldepfilelevel2.good())
    {
        std::cout << "node mdg file write fail" << symboldepfilelevel2path << "\n";
        exit(1);
    }

    std::string symboldepfileleveltpath = "symboldep_filelevel_t.mdg";
    std::ofstream symboldepfilelevelt;
    symboldepfilelevelt.open(symboldepfileleveltpath, std::ios::out | std::ios::trunc);
    if (!symboldepfilelevelt.good())
    {
        std::cout << "node mdg file write fail" << symboldepfileleveltpath << "\n";
        exit(1);
    }

    std::string symboldepfilelevel9path = "symboldep_filelevel_9.mdg";
    std::ofstream symboldepfilelevel9;
    symboldepfilelevel9.open(symboldepfilelevel9path, std::ios::out | std::ios::trunc);
    if (!symboldepfilelevel9.good())
    {
        std::cout << "node mdg file write fail" << symboldepfilelevel9path << "\n";
        exit(1);
    }

    std::string symboldepfilelevel10path = "symboldep_filelevel_10.mdg";
    std::ofstream symboldepfilelevel10;
    symboldepfilelevel10.open(symboldepfilelevel10path, std::ios::out | std::ios::trunc);
    if (!symboldepfilelevel10.good())
    {
        std::cout << "node mdg file write fail" << symboldepfilelevel10path << "\n";
        exit(1);
    }

    // symboldep << "[" << std::endl;

    int startidx = 0;
    bool begin = true;

    try
    {
        while (true)
        {
            std::string query = "SELECT * FROM symboldeptable limit " + std::to_string(startidx) + "," + std::to_string(MAX_BATCH_SIZE) + ";";
            stmt = con->createStatement();

            sql::ResultSet *rs = stmt->executeQuery(query);

            int num = rs->rowsCount();

            std::cout << num << std::endl;

            if (num == 0 && begin)
            {
                std::cout << "no symbol in symboldeptable!" << std::endl;

                exit(1);
            }
            else if (num == 0)
            {
                break;
            }

            while (rs->next())
            {
                int sdt = rs->getInt("sdeptype");
                // if((SDependencyType)sdt != SDT_Func_Function) continue;

                unsigned ssid = rs->getInt("ssid");
                unsigned esid = rs->getInt("esid");

                std::unordered_set<std::string> sfilepathset;
                std::unordered_set<std::string> efilepathset;

                if (USE_DEF_AND_DEC_TO_MAP)
                {
                    sfilepathset = getSymbolDefAndDecFilepath(ssid);
                    efilepathset = getSymbolDefAndDecFilepath(esid);
                }
                else
                {
                    sfilepathset = getSymbolDefFilepath(ssid);
                    efilepathset = getSymbolDefFilepath(esid);
                }

                if (sfilepathset.empty() && efilepathset.empty())
                    continue;

                if (sfilepathset.empty())
                    ssid = 0; // external
                if (efilepathset.empty())
                    esid = 0; // external

                if (begin)
                    begin = false;
                // else
                // symboldep << "\n" << std::endl;

                assert(ssid >= 0); // special external node==0
                assert(esid >= 0); // special external node==0
                assert(sdt >= 0);

                symboldep << ssid << " " << esid << " 1\n";

                depsidlist.insert(ssid);
                depsidlist.insert(esid);

                if (ssid == 0 || esid == 0)
                    continue;

                for (std::unordered_set<std::string>::iterator sitr = sfilepathset.begin(); sitr != sfilepathset.end(); ++sitr)
                {
                    for (std::unordered_set<std::string>::iterator eitr = efilepathset.begin(); eitr != efilepathset.end(); ++eitr)
                    {
                        symboldepfilelevelall << *sitr << " " << *eitr << "\n";
                        if (sdt == 0)
                        {
                            symboldepfilelevel0 << *sitr << " " << *eitr << "\n";
                        }
                        else if (sdt == 1)
                            symboldepfilelevel1 << *sitr << " " << *eitr << "\n";
                        else if (sdt == 2)
                            symboldepfilelevel2 << *sitr << " " << *eitr << "\n";
                        else if (sdt >= 3 && sdt <= 7)
                        {
                            symboldepfilelevelt << *sitr << " " << *eitr << "\n";
                        }
                        else if (sdt == 9)
                            symboldepfilelevel9 << *sitr << " " << *eitr << "\n";
                        else if (sdt == 10)
                            symboldepfilelevel10 << *sitr << " " << *eitr << "\n";
                    }
                }
            }
            // symbolnode << "]" << std::endl;

            symboldep.flush();

            symboldepfilelevelall.flush();
            symboldepfilelevel0.flush();
            symboldepfilelevel1.flush();
            symboldepfilelevel2.flush();
            symboldepfilelevelt.flush();
            symboldepfilelevel9.flush();
            symboldepfilelevel10.flush();

            delete rs;

            if (num < MAX_BATCH_SIZE)
            {
                symboldep.close();

                symboldepfilelevelall.close();
                symboldepfilelevel0.close();
                symboldepfilelevel1.close();
                symboldepfilelevel2.close();
                symboldepfilelevelt.close();
                symboldepfilelevel9.close();
                symboldepfilelevel10.close();
                break;
            }
            else
            {
                startidx += MAX_BATCH_SIZE;
            }
        }
    }
    catch (sql::SQLException &e)
    {
        std::cout << "ERROR: " << e.what();
        std::cout << " (MySQL error code: " << e.getErrorCode();
        std::cout << ", SQLState: " << e.getSQLState() << ")" << std::endl;

        if (e.getErrorCode() == 1047)
        {
            /*
            Error: 1047 SQLSTATE: 08S01 (ER_UNKNOWN_COM_ERROR)
            Message: Unknown command
            */
            std::cout << "/nYour server does not seem to support Prepared Statements at all. ";
            std::cout << "Perhaps MYSQL < 4.1?" << std::endl;
        }

        exit(1);
    }
    catch (std::runtime_error &e)
    {
        std::cout << "ERROR: " << e.what() << std::endl;

        exit(1);
    }
}

std::string Connector::getRelativeFilePath(std::string filepath)
{
    std::string::size_type idx = filepath.find(directory);
    if (idx == std::string::npos)
    { // if it's not internal, return empty string
        filepath.clear();
    }
    else
    {
        if (idx != 0)
        {
            std::cout << "wrong currfile!" << std::endl;
            std::cout << idx << std::endl;
            std::cout << filepath << std::endl;
            std::cout << directory << std::endl;
            exit(1);
        }
        filepath = filepath.substr(directory.size() + 1);
    }

    return filepath;
}

void Connector::dumpFileDefSymMap()
{
    // filedefsymbol << "[" << std::endl;

    // searchdef

    int startidx = 0;
    bool begin = true;

    try
    {
        while (true)
        {
            std::string query = "select * from globaldeftable,symboltable where symboltable.sid = globaldeftable.sid limit " + std::to_string(startidx) + "," + std::to_string(MAX_BATCH_SIZE) + ";";
            stmt = con->createStatement();

            sql::ResultSet *rs = stmt->executeQuery(query);

            int num = rs->rowsCount();

            std::cout << num << std::endl;

            if (num == 0 && begin)
            {
                std::cout << "no symbol in deftable!" << std::endl;

                exit(1);
            }
            else if (num == 0)
            {
                break;
            }

            while (rs->next())
            {
                if (begin)
                    begin = false;
                // else
                // symboldep << "\n" << std::endl;

                unsigned fid = rs->getInt("fid");
                std::string name = rs->getString("name");

                assert(fid > 0);
                assert(!name.empty());
                if (filedefsymbolmap.find(fid) == filedefsymbolmap.end())
                {
                    std::unordered_set<std::string> newset;
                    newset.insert(name);
                    filedefsymbolmap[fid] = newset;
                }
                else
                {
                    filedefsymbolmap[fid].insert(name);
                }
            }
            // symboldep << "]" << std::endl;

            // symboldep.flush();
            delete rs;

            if (num < MAX_BATCH_SIZE)
            {
                // symboldep.close();
                break;
            }
            else
            {
                startidx += MAX_BATCH_SIZE;
            }
        }
    }
    catch (sql::SQLException &e)
    {
        std::cout << "ERROR: " << e.what();
        std::cout << " (MySQL error code: " << e.getErrorCode();
        std::cout << ", SQLState: " << e.getSQLState() << ")" << std::endl;

        if (e.getErrorCode() == 1047)
        {
            /*
            Error: 1047 SQLSTATE: 08S01 (ER_UNKNOWN_COM_ERROR)
            Message: Unknown command
            */
            std::cout << "/nYour server does not seem to support Prepared Statements at all. ";
            std::cout << "Perhaps MYSQL < 4.1?" << std::endl;
        }

        exit(1);
    }
    catch (std::runtime_error &e)
    {
        std::cout << "ERROR: " << e.what() << std::endl;

        exit(1);
    }

    // searchdec

    startidx = 0;
    begin = true;

    try
    {
        while (true)
        {
            std::string query = "select * from globaldectable,symboltable where symboltable.sid = globaldectable.sid limit " + std::to_string(startidx) + "," + std::to_string(MAX_BATCH_SIZE) + ";";
            stmt = con->createStatement();

            sql::ResultSet *rs = stmt->executeQuery(query);

            int num = rs->rowsCount();

            std::cout << num << std::endl;

            if (num == 0 && begin)
            {
                std::cout << "no symbol in dectable!" << std::endl;

                exit(1);
            }
            else if (num == 0)
            {
                break;
            }

            while (rs->next())
            {
                if (begin)
                    begin = false;
                // else
                // symboldep << "\n" << std::endl;

                unsigned fid = rs->getInt("fid");
                std::string name = rs->getString("name");

                assert(fid > 0);
                assert(!name.empty());
                if (filedefsymbolmap.find(fid) == filedefsymbolmap.end())
                {
                    std::unordered_set<std::string> newset;
                    newset.insert(name);
                    filedefsymbolmap[fid] = newset;
                }
                else
                {
                    filedefsymbolmap[fid].insert(name);
                }
            }
            // symbolnode << "]" << std::endl;

            // symboldep.flush();
            delete rs;

            if (num < MAX_BATCH_SIZE)
            {
                // symboldep.close();
                break;
            }
            else
            {
                startidx += MAX_BATCH_SIZE;
            }
        }
    }
    catch (sql::SQLException &e)
    {
        std::cout << "ERROR: " << e.what();
        std::cout << " (MySQL error code: " << e.getErrorCode();
        std::cout << ", SQLState: " << e.getSQLState() << ")" << std::endl;

        if (e.getErrorCode() == 1047)
        {
            /*
            Error: 1047 SQLSTATE: 08S01 (ER_UNKNOWN_COM_ERROR)
            Message: Unknown command
            */
            std::cout << "/nYour server does not seem to support Prepared Statements at all. ";
            std::cout << "Perhaps MYSQL < 4.1?" << std::endl;
        }

        exit(1);
    }
    catch (std::runtime_error &e)
    {
        std::cout << "ERROR: " << e.what() << std::endl;

        exit(1);
    }

    std::string filedefsymbolpath = "filedefsymbol.json";
    std::ofstream filedefsymbol;
    filedefsymbol.open(filedefsymbolpath, std::ios::out | std::ios::trunc);
    if (!filedefsymbol.good())
    {
        std::cout << "file def file write fail" << filedefsymbolpath << "\n";
        exit(1);
    }

    filedefsymbol << "[" << std::endl;

    bool outerbegin = true;

    for (std::unordered_map<unsigned, std::unordered_set<std::string>>::iterator iter = filedefsymbolmap.begin(); iter != filedefsymbolmap.end(); iter++)
    {
        std::string currfilepath = getfilepath(iter->first);

        currfilepath = getRelativeFilePath(currfilepath);

        std::unordered_set<std::string> s = iter->second;
        if (s.empty())
            continue;

        if (outerbegin)
            outerbegin = false;
        else
        {
            filedefsymbol << "," << std::endl;
        }
        filedefsymbol << "{" << std::endl;

        filedefsymbol << "\"name\" : \"" << currfilepath << "\"," << std::endl;
        filedefsymbol << "\"sym_num\" : " << s.size() << "," << std::endl;
        filedefsymbol << "\"symbol\" : [";

        bool innerbegin = true;
        for (std::unordered_set<std::string>::iterator ii = s.begin(); ii != s.end(); ii++)
        {
            if (innerbegin)
                innerbegin = false;
            else
                filedefsymbol << ",";

            filedefsymbol << "\"" << (*ii) << "\"";
        }
        filedefsymbol << "]" << std::endl;
        filedefsymbol << "}" << std::endl;
    }

    filedefsymbol << "]" << std::endl;

    filedefsymbol.flush();

    filedefsymbol.close();
}

void Connector::dumpNewVectors()
{
    if (vectorsfile.empty())
        return;

    std::ifstream in;

    in.open(vectorsfile, std::ios::in);
    if (!in.good())
    {
        std::cout << "vectors file open fail@" << vectorsfile << "\n";
        exit(1);
    }
    std::string line;
    std::vector<std::string> col;

    std::string newvectorspath = "symbolvectors.txt";
    std::ofstream newvectors;
    newvectors.open(newvectorspath, std::ios::out | std::ios::trunc);
    if (!newvectors.good())
    {
        std::cout << "new vectors file write fail" << newvectorspath << "\n";
        exit(1);
    }
    newvectors << "0 ";
    for (int i = 0; i < SYMBOL_VECTOR_DIM - 1; ++i)
    {
        newvectors << "1 ";
    }
    newvectors << "1" << std::endl;

    while (getline(in, line) && in.good())
    {
        std::string::size_type epos = line.find(' ');
        if (epos == std::string::npos)
        {
            std::cout << "error format@" << line << "\n";
            exit(1);
        }

        std::string symbolname = line.substr(0, epos);
        assert(symbolname.size() > 0);

        try
        {
            std::string query = "SELECT * FROM symboltable WHERE symboltype=" + std::to_string((int)ST_Function) + " AND signature=\"" + symbolname + "\";";
            stmt = con->createStatement();

            sql::ResultSet *rs = stmt->executeQuery(query);

            int num = rs->rowsCount();

            if (num == 0)
            {
                std::cout << "no symbol in symboltable! sig is:" << symbolname << std::endl;
                continue;
            }

            if (num > 1)
            {
                std::cout << "WARNING:more than 1 symbol in symboltable! sig is:" << symbolname << std::endl;
                exit(1);
            }

            while (rs->next())
            {
                unsigned sid = rs->getInt("sid");

                assert(sid > 0);

                newvectors << sid << line.substr(epos) << std::endl;
            }

            newvectors.flush();
            delete rs;
        }
        catch (sql::SQLException &e)
        {
            std::cout << "ERROR: " << e.what();
            std::cout << " (MySQL error code: " << e.getErrorCode();
            std::cout << ", SQLState: " << e.getSQLState() << ")" << std::endl;

            if (e.getErrorCode() == 1047)
            {
                /*
                Error: 1047 SQLSTATE: 08S01 (ER_UNKNOWN_COM_ERROR)
                Message: Unknown command
                */
                std::cout << "/nYour server does not seem to support Prepared Statements at all. ";
                std::cout << "Perhaps MYSQL < 4.1?" << std::endl;
            }

            exit(1);
        }
        catch (std::runtime_error &e)
        {
            std::cout << "ERROR: " << e.what() << std::endl;

            exit(1);
        }

    } // endread while

    newvectors.close();
    in.close();
}

void Connector::dumpOnehotVectors()
{
    // dump one hot

    std::string onehotvectorspath = "symbolvectors-onehot.txt";
    std::ofstream onehotvectors;
    onehotvectors.open(onehotvectorspath, std::ios::out | std::ios::trunc);
    if (!onehotvectors.good())
    {
        std::cout << "new vectors file write fail" << onehotvectorspath << "\n";
        exit(1);
    }

    int dim = depsidlist.size();

    assert(dim > 0);
    int i = 0;
    for (const auto &iter : depsidlist)
    {
        // for(int i = 0;i<dim;++i){//n symbol
        onehotvectors << iter << " ";
        for (int j = 0; j < dim; ++j)
        {
            if (j == i)
                onehotvectors << '1';
            else
                onehotvectors << '0';

            if (j == dim - 1)
                onehotvectors << std::endl;
            else
                onehotvectors << ' ';
        }
        ++i;
    }
    if (i != dim)
    {
        std::cout << "internal error! i==" << i << "dim ==" << (dim) << "\n";
        exit(1);
    }

    onehotvectors.flush();
    onehotvectors.close();
}

void Connector::dumpRefNode(std::string tablename)
{
    std::cout << "dumping  " << tablename << "!" << std::endl;

    std::string symbolnodepath = "refnode.json";
    std::ofstream symbolnode;
    symbolnode.open(symbolnodepath, std::ios::out | std::ios::app);
    if (!symbolnode.good())
    {
        std::cout << "refnode json file write fail" << symbolnodepath << "\n";
        exit(1);
    }

    int startidx = 0;
    bool begin = true; //',' output before call this function if needed

    try
    {

        while (true)
        {
            std::string query = "SELECT * FROM " + tablename + " limit " + std::to_string(startidx) + "," + std::to_string(MAX_BATCH_SIZE) + ";";

            stmt = con->createStatement();

            sql::ResultSet *rs = stmt->executeQuery(query);

            int num = rs->rowsCount();
            std::cout << num << std::endl;

            if (num == 0 && begin)
            {
                std::cout << "no symbol in " << tablename << "!" << std::endl;

                exit(1);
            }
            else if (num == 0)
            {
                break;
            }

            while (rs->next())
            {

                if (begin)
                    begin = false;
                else
                    symbolnode << "," << std::endl;

                unsigned refid = rs->getInt("refid");
                unsigned sid = rs->getInt("sid");
                int rt = rs->getInt("reftype");
                unsigned fid = rs->getInt("fid");
                std::string location = rs->getString("location");
                assert(refid > 0);
                assert(rt >= 0);

                std::string name = getSymbolName(sid);
                std::string filepath = getfilepath(fid);

                symbolnode << "{" << std::endl;
                symbolnode << "\"refid\" : " << refid << "," << std::endl;
                symbolnode << "\"sid\" : " << sid << "," << std::endl;
                symbolnode << "\"reftype\" : \"" << refTypeNames[rt] << "\"," << std::endl;
                symbolnode << "\"fid\" : " << fid << "," << std::endl;
                symbolnode << "\"location\" : \"" << location << "\"" << std::endl;
                symbolnode << "}" << std::endl;
            }

            symbolnode.flush();

            delete rs;

            if (num < MAX_BATCH_SIZE)
            {
                symbolnode.close();
                break;
            }
            else
            {
                startidx += MAX_BATCH_SIZE;
            }
        }
    }
    catch (sql::SQLException &e)
    {
        std::cout << "ERROR: " << e.what();
        std::cout << " (MySQL error code: " << e.getErrorCode();
        std::cout << ", SQLState: " << e.getSQLState() << ")" << std::endl;

        if (e.getErrorCode() == 1047)
        {
            /*
            Error: 1047 SQLSTATE: 08S01 (ER_UNKNOWN_COM_ERROR)
            Message: Unknown command
            */
            std::cout << "/nYour server does not seem to support Prepared Statements at all. ";
            std::cout << "Perhaps MYSQL < 4.1?" << std::endl;
        }

        exit(1);
    }
    catch (std::runtime_error &e)
    {
        std::cout << "ERROR: " << e.what() << std::endl;

        exit(1);
    }

    symbolnode.close();
}

void Connector::findFileDep()
{

    // unsigned fid = getfid(filepath);
    if (currfid <= 0)
        return;

    std::cout << "fid = " << currfid << std::endl;

    std::string query = "SELECT sid,reftype FROM reftable where fid = " + std::to_string(currfid) + ";";
    stmt = con->createStatement();

    sql::ResultSet *rs = stmt->executeQuery(query);

    int num = rs->rowsCount();

    std::cout << "num = " << num << std::endl;

    if (num == 0)
    {
        std::cout << "no symbol reference found in" << currfilepath << std::endl;
        delete rs;
        return;
    }

    while (rs->next())
    {
        unsigned sid = rs->getInt("sid");
        int rt = rs->getInt("reftype");

        assert(sid > 0);
        std::cout << rs << std::endl;

        if (rt == RT_Included)
        {

            std::string path = getSymbolQN(sid);
            assert(path[0] == '@');

            path = path.substr(1);
            unsigned incfid = getfid(path);

            assert(incfid >= 0);

            if (incfid == 0)
                continue; // This header file is empty, can ignore!

            std::string includefilepath = "includeedge.json";
            std::ofstream includefile;
            includefile.open(includefilepath, std::ios::out | std::ios::app);
            if (!includefile.good())
            {
                std::cout << "include json file write fail" << includefilepath << "\n";
                exit(1);
            }

            if (includebegin)
                includebegin = false;
            else
                includefile << "," << std::endl;

            includefile << "{" << std::endl;
            includefile << "\"startnode\" : " << currfid << "," << std::endl;
            includefile << "\"endnode\" : " << incfid << std::endl;
            includefile << "}" << std::endl;
            includefile.flush();

            includefile.close();

            std::string incmdgfilepath = "include.mdg";
            std::ofstream incmdgfile;
            incmdgfile.open(incmdgfilepath, std::ios::out | std::ios::app);
            if (!incmdgfile.good())
            {
                std::cout << "mdg file write fail" << incmdgfilepath << "\n";
                exit(1);
            }

            std::string relcurrfilepath = getRelativeFilePath(currfilepath);
            std::string depfile = getRelativeFilePath(path);

            bool incmdgprint = true;

            if (relcurrfilepath.empty() || depfile.empty())
                incmdgprint = false;

            if (incmdgprint)
            {
                incmdgfile << relcurrfilepath << " " << depfile << std::endl;
                std::cout << relcurrfilepath << " " << depfile << std::endl;

                std::string inctsejsonfilepath = "includeedge_internal.json";
                std::ofstream inctsejsonfile;
                inctsejsonfile.open(inctsejsonfilepath, std::ios::out | std::ios::app);
                if (!inctsejsonfile.good())
                {
                    std::cout << "inctsejsonfile write fail" << inctsejsonfilepath << "\n";
                    exit(1);
                }

                if (includetsebegin)
                    includetsebegin = false;
                else
                    inctsejsonfile << "," << std::endl;

                inctsejsonfile << "{" << std::endl;
                inctsejsonfile << "\"startnode\" : " << currfid << "," << std::endl;
                inctsejsonfile << "\"endnode\" : " << incfid << std::endl;
                inctsejsonfile << "}" << std::endl;
            }

            incmdgfile.close();
            includefile.flush();

            includefile.close();

            continue;
        }

        std::cout << "sid = " << sid << std::endl;

        SymbolType st = getSymbolType(sid);

        searchDef(sid, currfid, st);
        if (USE_DEF_AND_DEC_TO_MAP)
            searchDec(sid, currfid, st);
    }

    dumpDepFileList();
    dumpDepFileList_funct();
    dumpDepFileList_gv();
    dumpDepFileList_macro();
    dumpDepFileList_type();
    dumpDepFileList_enum();
    dumpDepFileList_struct();
    dumpDepFileList_union();
    dumpDepFileList_typedef();
    dumpDepFileList_field();
    dumpDepFileList_functgv();
    delete rs;
    std::cout << "ok dump file list" << std::endl;
}

void Connector::dumpDepFileList()
{

    if (depfilelist.empty())
    {
        std::cout << "no dep file empty! @" << currfilepath << std::endl;
        return;
    }

    int n = depfilelist.size();

    std::ofstream jsonfile;
    std::string jsonfilepath = "edge.json";

    if (connbegin)
        connbegin = false;
    else
    {
        jsonfile.open(jsonfilepath, std::ios::out | std::ios::app);
        if (!jsonfile.good())
        {
            std::cout << "json file write fail" << jsonfilepath << "\n";
            exit(1);
        }

        jsonfile << "," << std::endl;
        jsonfile.flush();
        jsonfile.close();
    }

    jsonfile.open(jsonfilepath, std::ios::out | std::ios::app);
    if (!jsonfile.good())
    {
        std::cout << "json file write fail" << jsonfilepath << "\n";
        exit(1);
    }

    std::cout << "Found " << n << " dependency files:" << std::endl;

    bool begin = true;

    for (const auto &iter : depfilelist)
    {

        assert(iter != currfid);

        if (begin)
            begin = false;
        else
            jsonfile << ",";

        jsonfile << "{" << std::endl;
        jsonfile << "\"startnode\" : " << currfid << ",\n";
        jsonfile << "\"endnode\" : " << iter << ",\n";

        jsonfile.flush();
        jsonfile.close();

        std::string symmdgfilepath = "symbol.mdg";
        std::ofstream symmdgfile;
        symmdgfile.open(symmdgfilepath, std::ios::out | std::ios::app);
        if (!symmdgfile.good())
        {
            std::cout << "mdg file write fail" << symmdgfilepath << "\n";
            exit(1);
        }

        //////////////////////////
        std::ofstream symtsejsonfile;
        std::string symtsejsonfilepath = "edge_internal.json";
        symtsejsonfile.open(symtsejsonfilepath, std::ios::out | std::ios::app);
        if (!symtsejsonfile.good())
        {
            std::cout << "symtsejsonfile write fail" << symtsejsonfilepath << "\n";
            exit(1);
        }

        std::string relcurrfilepath = getRelativeFilePath(currfilepath);
        std::string depfile = getRelativeFilePath(getfilepath(iter));

        bool symmdgprint = true;

        if (relcurrfilepath.empty() || depfile.empty())
            symmdgprint = false;

        if (symmdgprint)
        {
            symmdgfile << relcurrfilepath << " " << depfile << std::endl;
            std::cout << relcurrfilepath << " " << depfile << std::endl;

            if (symboltsebegin)
                symboltsebegin = false;
            else
            {
                symtsejsonfile << "," << std::endl;
            }

            symtsejsonfile << "{" << std::endl;
            symtsejsonfile << "\"startnode\" : " << currfid << "," << std::endl;
            symtsejsonfile << "\"endnode\" : " << iter << "," <<std::endl;

            // symmdgfile.flush();
        }

        symtsejsonfile.flush();
        symtsejsonfile.close();

        symmdgfile.close();

        dumpFileSymbol(iter, symmdgprint);

        jsonfile.open(jsonfilepath, std::ios::out | std::ios::app);
        if (!jsonfile.good())
        {
            std::cout << "json file write fail" << jsonfilepath << "\n";
            exit(1);
        }

        jsonfile << "}" << std::endl;

        //////////////////////////
        symtsejsonfile.open(symtsejsonfilepath, std::ios::out | std::ios::app);
        if (!symtsejsonfile.good())
        {
            std::cout << "symtsejsonfile write fail" << symtsejsonfilepath << "\n";
            exit(1);
        }

        if (symmdgprint) symtsejsonfile << "}" << std::endl;

        symtsejsonfile.flush();
        symtsejsonfile.close();

    }

    jsonfile.close();
}

void Connector::dumpFileSymbol(unsigned fid, bool symmdgprint)
{
    std::cout << "in dump file symbol: ref file id = " << fid << std::endl;
    assert(fid > 0);
    if (depfilelist.count(fid) == 0)
    {
        std::cout << "invalid fid!@" << fid << std::endl;
        exit(1);
    }

    if (filesymbolmap.count(fid) == 0)
    {
        std::cout << "INTERNAL ERROR!can't find fid symbol table!@" << fid << std::endl;
        exit(1);
    }

    std::ofstream jsonfile;
    std::string jsonfilepath = "edge.json";
    jsonfile.open(jsonfilepath, std::ios::out | std::ios::app);

    if (!jsonfile.good())
    {
        std::cout << "symbol json file write fail" << jsonfilepath << "\n";
        exit(1);
    }

    //////////////////////////
    std::ofstream symtsejsonfile;
    std::string symtsejsonfilepath = "edge_internal.json";
    symtsejsonfile.open(symtsejsonfilepath, std::ios::out | std::ios::app);
    if (!symtsejsonfile.good())
    {
        std::cout << "symtsejsonfile write fail" << symtsejsonfilepath << "\n";
        exit(1);
    }

    // symboltable
    jsonfile << "\"ref\" : [" << std::endl;
    if(symmdgprint) symtsejsonfile<< "\"ref\" : [" << std::endl;

    const auto &s = filesymbolmap[fid];

    bool begin = true;

    int counter = 0;
    for (const auto &iter : s)
    {
        ++counter;
        unsigned refid = iter;

        if (begin)
            begin = false;
        else{
            jsonfile << "," << std::endl;
            if(symmdgprint) symtsejsonfile << "," << std::endl;
        }

        jsonfile << std::to_string(refid) << std::endl;
        if(symmdgprint) symtsejsonfile<< std::to_string(refid) << std::endl;

        // dump ref info
    }

    jsonfile << "]" << std::endl;
    if(symmdgprint) symtsejsonfile<< "]" << std::endl;

    jsonfile.flush();
    jsonfile.close();

    symtsejsonfile.flush();
    symtsejsonfile.close();
}

void Connector::dumpDepFileList_funct()
{

    if (depfilelist_funct.empty())
    {
        std::cout << "funct: no dep file empty! @" << currfilepath << std::endl;
        return;
    }

    int n = depfilelist_funct.size();

    ////////////////////////////////////////////////
    std::string funtsejsonfilepath = "functionedge_internal.json";
    std::ofstream funtsejsonfile;
    funtsejsonfile.open(funtsejsonfilepath, std::ios::out | std::ios::app);
    if (!funtsejsonfile.good())
    {
        std::cout << "funtsejsonfile write fail" << funtsejsonfilepath << "\n";
        exit(1);
    }

    std::string functmdgfilepath = "function.mdg";
    std::ofstream functmdgfile;
    functmdgfile.open(functmdgfilepath, std::ios::out | std::ios::app);
    if (!functmdgfile.good())
    {
        std::cout << "mdg file write fail" << functmdgfilepath << "\n";
        exit(1);
    }

    for (const auto &iter : depfilelist_funct)
    {

        assert(iter != currfid);

        std::string relcurrfilepath = getRelativeFilePath(currfilepath);
        std::string depfile = getRelativeFilePath(getfilepath(iter));

        bool functmdgprint = true;

        if (relcurrfilepath.empty() || depfile.empty())
            functmdgprint = false;

        if (functmdgprint)
        {
            functmdgfile << relcurrfilepath << " " << depfile << "\n";
            std::cout << relcurrfilepath << " " << depfile << std::endl;

            if (funtsebegin)
                funtsebegin = false;
            else
            {
                funtsejsonfile << "," << std::endl;
            }

            funtsejsonfile << "{" << std::endl;
            funtsejsonfile << "\"startnode\" : " << currfid << "," << std::endl;
            funtsejsonfile << "\"endnode\" : " << iter << std::endl;
            funtsejsonfile << "}" << std::endl;

            funtsejsonfile.flush();
        }
    }

    funtsejsonfile.close();

    functmdgfile.close();
}

void Connector::dumpDepFileList_gv()
{

    if (depfilelist_gv.empty())
    {
        std::cout << "gv: no dep file empty! @" << currfilepath << std::endl;
        return;
    }

    int n = depfilelist_gv.size();

    std::string gvmdgfilepath = "gv.mdg";
    std::ofstream gvmdgfile;
    gvmdgfile.open(gvmdgfilepath, std::ios::out | std::ios::app);
    if (!gvmdgfile.good())
    {
        std::cout << "mdg file write fail" << gvmdgfilepath << "\n";
        exit(1);
    }

    for (const auto &iter : depfilelist_gv)
    {

        assert(iter != currfid);

        std::string relcurrfilepath = getRelativeFilePath(currfilepath);
        std::string depfile = getRelativeFilePath(getfilepath(iter));

        bool gvmdgprint = true;

        if (relcurrfilepath.empty() || depfile.empty())
            gvmdgprint = false;

        if (gvmdgprint)
        {
            gvmdgfile << relcurrfilepath << " " << depfile << "\n";
            std::cout << relcurrfilepath << " " << depfile << std::endl;
        }
    }
    gvmdgfile.close();
}

void Connector::dumpDepFileList_macro()
{

    if (depfilelist_macro.empty())
    {
        std::cout << "macro: no dep file empty! @" << currfilepath << std::endl;
        return;
    }

    int n = depfilelist_macro.size();

    std::string macromdgfilepath = "macro.mdg";
    std::ofstream macromdgfile;
    macromdgfile.open(macromdgfilepath, std::ios::out | std::ios::app);
    if (!macromdgfile.good())
    {
        std::cout << "mdg file write fail" << macromdgfilepath << "\n";
        exit(1);
    }

    for (const auto &iter : depfilelist_macro)
    {

        assert(iter != currfid);

        std::string relcurrfilepath = getRelativeFilePath(currfilepath);
        std::string depfile = getRelativeFilePath(getfilepath(iter));

        bool macromdgprint = true;

        if (relcurrfilepath.empty() || depfile.empty())
            macromdgprint = false;

        if (macromdgprint)
        {
            macromdgfile << relcurrfilepath << " " << depfile << "\n";
            std::cout << relcurrfilepath << " " << depfile << std::endl;
        }
    }
    macromdgfile.close();
}

void Connector::dumpDepFileList_type()
{

    if (depfilelist_type.empty())
    {
        std::cout << "type: no dep file empty! @" << currfilepath << std::endl;
        return;
    }

    int n = depfilelist_type.size();

    std::string typemdgfilepath = "type.mdg";
    std::ofstream typemdgfile;
    typemdgfile.open(typemdgfilepath, std::ios::out | std::ios::app);
    if (!typemdgfile.good())
    {
        std::cout << "mdg file write fail" << typemdgfilepath << "\n";
        exit(1);
    }

    for (const auto &iter : depfilelist_type)
    {

        assert(iter != currfid);

        std::string relcurrfilepath = getRelativeFilePath(currfilepath);
        std::string depfile = getRelativeFilePath(getfilepath(iter));

        bool typemdgprint = true;

        if (relcurrfilepath.empty() || depfile.empty())
            typemdgprint = false;

        if (typemdgprint)
        {
            typemdgfile << relcurrfilepath << " " << depfile << "\n";
            std::cout << relcurrfilepath << " " << depfile << std::endl;
        }
    }
    typemdgfile.close();
}

void Connector::dumpDepFileList_enum()
{

    if (depfilelist_enum.empty())
    {
        std::cout << "enum: no dep file empty! @" << currfilepath << std::endl;
        return;
    }

    int n = depfilelist_enum.size();

    std::string enummdgfilepath = "enum.mdg";
    std::ofstream enummdgfile;
    enummdgfile.open(enummdgfilepath, std::ios::out | std::ios::app);
    if (!enummdgfile.good())
    {
        std::cout << "mdg file write fail" << enummdgfilepath << "\n";
        exit(1);
    }

    for (const auto &iter : depfilelist_enum)
    {

        assert(iter != currfid);

        std::string relcurrfilepath = getRelativeFilePath(currfilepath);
        std::string depfile = getRelativeFilePath(getfilepath(iter));

        bool enummdgprint = true;

        if (relcurrfilepath.empty() || depfile.empty())
            enummdgprint = false;

        if (enummdgprint)
        {
            enummdgfile << relcurrfilepath << " " << depfile << "\n";
            std::cout << relcurrfilepath << " " << depfile << std::endl;
        }
    }
    enummdgfile.close();
}

void Connector::dumpDepFileList_struct()
{

    if (depfilelist_struct.empty())
    {
        std::cout << "struct: no dep file empty! @" << currfilepath << std::endl;
        return;
    }

    int n = depfilelist_struct.size();

    std::string structmdgfilepath = "struct.mdg";
    std::ofstream structmdgfile;
    structmdgfile.open(structmdgfilepath, std::ios::out | std::ios::app);
    if (!structmdgfile.good())
    {
        std::cout << "mdg file write fail" << structmdgfilepath << "\n";
        exit(1);
    }

    for (const auto &iter : depfilelist_struct)
    {

        assert(iter != currfid);

        std::string relcurrfilepath = getRelativeFilePath(currfilepath);
        std::string depfile = getRelativeFilePath(getfilepath(iter));

        bool structmdgprint = true;

        if (relcurrfilepath.empty() || depfile.empty())
            structmdgprint = false;

        if (structmdgprint)
        {
            structmdgfile << relcurrfilepath << " " << depfile << "\n";
            std::cout << relcurrfilepath << " " << depfile << std::endl;
        }
    }
    structmdgfile.close();
}

void Connector::dumpDepFileList_union()
{

    if (depfilelist_union.empty())
    {
        std::cout << "union: no dep file empty! @" << currfilepath << std::endl;
        return;
    }

    int n = depfilelist_union.size();

    std::string unionmdgfilepath = "union.mdg";
    std::ofstream unionmdgfile;
    unionmdgfile.open(unionmdgfilepath, std::ios::out | std::ios::app);
    if (!unionmdgfile.good())
    {
        std::cout << "mdg file write fail" << unionmdgfilepath << "\n";
        exit(1);
    }

    for (const auto &iter : depfilelist_union)
    {

        assert(iter != currfid);

        std::string relcurrfilepath = getRelativeFilePath(currfilepath);
        std::string depfile = getRelativeFilePath(getfilepath(iter));

        bool unionmdgprint = true;

        if (relcurrfilepath.empty() || depfile.empty())
            unionmdgprint = false;

        if (unionmdgprint)
        {
            unionmdgfile << relcurrfilepath << " " << depfile << "\n";
            std::cout << relcurrfilepath << " " << depfile << std::endl;
        }
    }
    unionmdgfile.close();
}

void Connector::dumpDepFileList_typedef()
{

    if (depfilelist_typedef.empty())
    {
        std::cout << "typedef: no dep file empty! @" << currfilepath << std::endl;
        return;
    }

    int n = depfilelist_typedef.size();

    std::string typedefmdgfilepath = "typedef.mdg";
    std::ofstream typedefmdgfile;
    typedefmdgfile.open(typedefmdgfilepath, std::ios::out | std::ios::app);
    if (!typedefmdgfile.good())
    {
        std::cout << "mdg file write fail" << typedefmdgfilepath << "\n";
        exit(1);
    }

    for (const auto &iter : depfilelist_typedef)
    {

        assert(iter != currfid);

        std::string relcurrfilepath = getRelativeFilePath(currfilepath);
        std::string depfile = getRelativeFilePath(getfilepath(iter));

        bool typedefmdgprint = true;

        if (relcurrfilepath.empty() || depfile.empty())
            typedefmdgprint = false;

        if (typedefmdgprint)
        {
            typedefmdgfile << relcurrfilepath << " " << depfile << "\n";
            std::cout << relcurrfilepath << " " << depfile << std::endl;
        }
    }
    typedefmdgfile.close();
}

void Connector::dumpDepFileList_field()
{

    if (depfilelist_field.empty())
    {
        std::cout << "field: no dep file empty! @" << currfilepath << std::endl;
        return;
    }

    int n = depfilelist_field.size();

    std::string fieldmdgfilepath = "field.mdg";
    std::ofstream fieldmdgfile;
    fieldmdgfile.open(fieldmdgfilepath, std::ios::out | std::ios::app);
    if (!fieldmdgfile.good())
    {
        std::cout << "mdg file write fail" << fieldmdgfilepath << "\n";
        exit(1);
    }

    for (const auto &iter : depfilelist_field)
    {

        assert(iter != currfid);

        std::string relcurrfilepath = getRelativeFilePath(currfilepath);
        std::string depfile = getRelativeFilePath(getfilepath(iter));

        bool fieldmdgprint = true;

        if (relcurrfilepath.empty() || depfile.empty())
            fieldmdgprint = false;

        if (fieldmdgprint)
        {
            fieldmdgfile << relcurrfilepath << " " << depfile << "\n";
            std::cout << relcurrfilepath << " " << depfile << std::endl;
        }
    }
    fieldmdgfile.close();
}

void Connector::dumpDepFileList_functgv()
{

    if (depfilelist_funct.empty() && depfilelist_gv.empty())
    {
        std::cout << "functgv: no dep file empty! @" << currfilepath << std::endl;
        return;
    }

    std::string fgvtsejsonfilepath = "fgvedge_internal.json";
    std::ofstream fgvtsejsonfile;
    fgvtsejsonfile.open(fgvtsejsonfilepath, std::ios::out | std::ios::app);
    if (!fgvtsejsonfile.good())
    {
        std::cout << "fgvtsejsonfile write fail" << fgvtsejsonfilepath << "\n";
        exit(1);
    }

    ////////////////////////////////////////////////

    std::string functgvmdgfilepath = "f-gv.mdg";
    std::ofstream functgvmdgfile;
    functgvmdgfile.open(functgvmdgfilepath, std::ios::out | std::ios::app);
    if (!functgvmdgfile.good())
    {
        std::cout << "mdg file write fail" << functgvmdgfilepath << "\n";
        exit(1);
    }

    for (const auto &iter : depfilelist_funct)
    {

        assert(iter != currfid);

        std::string relcurrfilepath = getRelativeFilePath(currfilepath);
        std::string depfile = getRelativeFilePath(getfilepath(iter));

        bool functgvmdgprint = true;

        if (relcurrfilepath.empty() || depfile.empty())
            functgvmdgprint = false;

        if (functgvmdgprint)
        {

            if (fgvtsebegin)
                fgvtsebegin = false;
            else
            {
                fgvtsejsonfile << "," << std::endl;
            }

            fgvtsejsonfile << "{" << std::endl;
            fgvtsejsonfile << "\"startnode\" : " << currfid << "," << std::endl;
            fgvtsejsonfile << "\"endnode\" : " << iter << std::endl;
            fgvtsejsonfile << "}" << std::endl;

            fgvtsejsonfile.flush();

            functgvmdgfile << relcurrfilepath << " " << depfile << "\n";
            std::cout << relcurrfilepath << " " << depfile << std::endl;
        }
    }

    for (const auto &iter : depfilelist_gv)
    {

        assert(iter != currfid);

        std::string relcurrfilepath = getRelativeFilePath(currfilepath);
        std::string depfile = getRelativeFilePath(getfilepath(iter));

        bool functgvmdgprint = true;

        if (relcurrfilepath.empty() || depfile.empty())
            functgvmdgprint = false;

        if (functgvmdgprint)
        {

            if (fgvtsebegin)
                fgvtsebegin = false;
            else
            {
                fgvtsejsonfile << "," << std::endl;
            }

            fgvtsejsonfile << "{" << std::endl;
            fgvtsejsonfile << "\"startnode\" : " << currfid << "," << std::endl;
            fgvtsejsonfile << "\"endnode\" : " << iter << std::endl;
            fgvtsejsonfile << "}" << std::endl;

            fgvtsejsonfile.flush();

            functgvmdgfile << relcurrfilepath << " " << depfile << "\n";
            std::cout << relcurrfilepath << " " << depfile << std::endl;
        }
    }

    fgvtsejsonfile.flush();
    fgvtsejsonfile.close();

    functgvmdgfile.close();
}

void Connector::searchDec(unsigned sid, unsigned notfid, SymbolType st)
{
    assert(sid > 0);
    assert(notfid > 0);

    std::string query = "SELECT refid,fid FROM globaldectable where sid =" + std::to_string(sid) + " AND fid !=" + std::to_string(notfid) + ";";
    std::cout << query << std::endl;
    stmt = con->createStatement();

    sql::ResultSet *rs = stmt->executeQuery(query);

    int num = rs->rowsCount();

    if (num == 0)
    {
        std::cout << "no external symbol dec found @" << sid << std::endl;
        delete rs;
        return;
    }

    while (rs->next())
    {

        unsigned refid = rs->getInt("refid");
        unsigned fid = rs->getInt("fid");

        if (filesymbolmap.count(fid) == 0)
        {
            std::unordered_set<unsigned> s;
            s.insert(refid);
            filesymbolmap.insert(make_pair(fid, s));
            depfilelist.insert(fid);
            if (st == ST_Function)
            {
                depfilelist_funct.insert(fid);
            }
            else if (st == ST_GlobalVariable)
                depfilelist_gv.insert(fid);
            else if (st == ST_Macro)
                depfilelist_macro.insert(fid);
            else if (st == ST_Enum || st == ST_Struct || st == ST_Typedef || st == ST_Union)
            {
                depfilelist_type.insert(fid);
                if (st == ST_Enum)
                    depfilelist_enum.insert(fid);
                else if (st == ST_Struct)
                    depfilelist_struct.insert(fid);
                else if (st == ST_Union)
                    depfilelist_union.insert(fid);
                else if (st == ST_Typedef)
                    depfilelist_typedef.insert(fid);
            }

            else if (st == ST_Enumerator || st == ST_Field)
                depfilelist_field.insert(fid);
        }
        else
        {
            filesymbolmap[fid].insert(refid);
        }
    }
    delete rs;
}

void Connector::searchDef(unsigned sid, unsigned notfid, SymbolType st)
{
    assert(sid > 0);
    assert(notfid > 0);

    std::string query = "SELECT refid,fid FROM globaldeftable where sid =" + std::to_string(sid) + " AND fid !=" + std::to_string(notfid) + ";";
    std::cout << query << std::endl;
    stmt = con->createStatement();

    sql::ResultSet *rs = stmt->executeQuery(query);

    int num = rs->rowsCount();

    if (num == 0)
    {
        std::cout << "no external symbol def found @" << sid << std::endl;
        delete rs;
        return;
    }

    while (rs->next())
    {

        unsigned refid = rs->getInt("refid");
        unsigned fid = rs->getInt("fid");

        if (filesymbolmap.count(fid) == 0)
        {
            std::unordered_set<unsigned> s;
            s.insert(refid);
            filesymbolmap.insert(make_pair(fid, s));
            depfilelist.insert(fid);
            if (st == ST_Function)
            {
                depfilelist_funct.insert(fid);
            }
            else if (st == ST_GlobalVariable)
                depfilelist_gv.insert(fid);
            else if (st == ST_Macro)
                depfilelist_macro.insert(fid);
            else if (st == ST_Enum || st == ST_Struct || st == ST_Typedef || st == ST_Union)
            {
                depfilelist_type.insert(fid);
                if (st == ST_Enum)
                    depfilelist_enum.insert(fid);
                else if (st == ST_Struct)
                    depfilelist_struct.insert(fid);
                else if (st == ST_Union)
                    depfilelist_union.insert(fid);
                else if (st == ST_Typedef)
                    depfilelist_typedef.insert(fid);
            }
            else if (st == ST_Enumerator || st == ST_Field)
                depfilelist_field.insert(fid);
        }
        else
        {
            filesymbolmap[fid].insert(refid);
        }
    }
    delete rs;
}
